This
notebook is Part 2 of “Introductory Big Data Analyses to gain insights
in Precision Medicine” course.
R setup | Install software
R setup | Packages
install.packages('dplyr', depencies=TRUE)
library(dplyr)
Download data and open file in R
Download data from exorbase
website.
Open file in R
hcc_rna<-read.delim(file.choose(),header=TRUE)
Other functions to open file

R packages for Data wrangling
- A typical data science project :

Reference: Grolemund, G., & Wickham, H. (2017). R for Data
Science. O’Reilly Media.
Step 1 Data wrangling using dplyr packages
1. Load dplyr package
library(dplyr)
3. Arrange rows
# arrange (data frame, column name)
hcc_sort<-arrange(hcc_rna, Gene.symbol)
#sort by more than one variable
hcc_sort<-arrange(hcc_rna, HCC001,Gene.symbol)
4. Select columns
# select (data frame, column name 1, column name 2)
hcc_select<-select(hcc_rna, Gene.symbol, HCC004)
5. Select all columns except specific column
# select (data frame, -columns that you don't want)
hcc_all<-select(hcc_rna, -c(Gene.symbol, HCC004))
6. Recode data
eg. Calculate how many patients that have RNA expression >0 and
store this value in a new column called “counthighexp”
# mutate (data frame, new column name = functions)
hcc_highexp<-mutate(hcc_rna,counthighexp=rowSums(hcc_rna>0))
eg. Recode numeric values to categories
# mutate (data frame, new column name = functions)
hcc_highexp <-mutate(hcc_highexp, cat = case_when(
counthighexp < 50 ~ "low",
counthighexp >= 50 ~ "high"))
7. Summarize data
summarize(hcc_highexp,mean(counthighexp))
8. Handle relational data (Multiple tables of data)




Reference: Grolemund, G., & Wickham, H. (2017). R for Data
Science. O’Reilly Media.
# inner_join (data frame 1, data frame 2, by="key")
hcc_healthy<-inner_join(hcc_rna,healthy_rna, by="Gene.symbol")
Exercise 1
Generate a mastersheet by merging hcc_rna
dataset and healthy_rna dataset. Name the new
mastersheet as hcc_healthy.
Question:
What type of join will you use for this dataset?
Summarize number of genes from
hcc_healthy.
In hcc_healthy, use Gene.symbol column as row
names of the table.
#without any package: data.frame(dataset name, row.names = column number)
#using tidyverse package: column_to_rownames(dataset name , var="key")
- Then, remove genes that have 0 expression in 90% of samples in the
dataset. Name the dataset as hcc_healthy_highexp
- Summarize the number of genes that have expression value >0 in
90% of the samples.
- Normalize all gene expressions using the log2 transformation. Name
the dataset as hcc_healthy_log
#log((data frame+1),2)
Exercise 1 answers
#merge hcc_rna with healthy_rna
hcc_healthy<-full_join(hcc_rna,healthy_rna)
#35517 genes
#convert gene symbol column to rownames
hcc_healthy <- data.frame(hcc_healthy, row.names = 1)
#remove genes that has 0 expression in 90% of samples in both datasets
hcc_healthy<-mutate(hcc_healthy,count0=rowSums(hcc_healthy<=0))
hcc_healthy_highexp<-filter(hcc_healthy,count0<=207)
hcc_healthy_highexp<-select(hcc_healthy_highexp,-count0)
#18,575 genes left
#log transformation of the data
hcc_healthy_log<-log((hcc_healthy_highexp+1),2)
About Data normalization
- Log transformation - to moderate the variance across the mean

- Reason to use Log2 instead of Log10

- Reason for expression value + 1 before log transformation

Step 3a Data visualization (Basic histogram)
R packages for data visualizations
#Install packages
install.packages("ggplot2",dependencies=TRUE)
install.packages("ggpubr",dependencies=TRUE)
#Load packages
library(ggplot2)
library(ggpubr)

Reference: https://rstudio.github.io/cheatsheets/data-visualization.pdf
Let’s visualize the the dataset before and after normalization
- Transpose the dataset
#Transpose the datasets so that the RNA names are in columns while samples are in rows
raw_trans<-data.frame(t(hcc_healthy))
normalize_trans<-data.frame(t(hcc_healthy_log))
- Draw histogram using ggplot
#select one of the RNA (ABCB1 as example)
#use ggplot to draw histogram and modify the binwidth and colour
rawgraph<-ggplot(raw_trans,aes(x=ABCB1))+geom_histogram(binwidth=0.5,fill="deepskyblue")
normalizegraph<-ggplot(normalize_trans,aes(x=ABCB1))+geom_histogram(binwidth=0.5,fill="deepskyblue")
- Place the histogram side by side for better comparison
ggarrange(rawgraph,normalizegraph,ncol=2,nrow=1,labels=c("raw","normalize"))
Useful resources to explore further

Save the R codes and environment - for next
section!
LS0tDQp0aXRsZTogIkRhdGEgV3JhbmdsaW5nIG5vdGVib29rIg0Kb3V0cHV0OiANCiAgaHRtbF9ub3RlYm9vazoNCiAgICB0b2M6IHllcw0KICAgIHRoZW1lOiByZWFkYWJsZQ0KLS0tDQoNCj4gIyMjIyMjICpUaGlzIG5vdGVib29rIGlzIFBhcnQgMiBvZiAiSW50cm9kdWN0b3J5IEJpZyBEYXRhIEFuYWx5c2VzIHRvIGdhaW4gaW5zaWdodHMgaW4gUHJlY2lzaW9uIE1lZGljaW5lIiBjb3Vyc2UuKg0KDQojIyBSIHNldHVwIFx8IEluc3RhbGwgc29mdHdhcmUNCg0KLSAgIERvd25sb2FkIGFuZCBpbnN0YWxsIFIgW1w8aHR0cHM6Ly9jbG91ZC5yLXByb2plY3Qub3JnL2Jpbi93aW5kb3dzL2Jhc2UvXD5dKGh0dHBzOi8vY2xvdWQuci1wcm9qZWN0Lm9yZy9iaW4vd2luZG93cy9iYXNlLyl7LnVyaX0NCg0KLSAgIERvd25sb2FkIGFuZCBpbnN0YWxsIFJzdHVkaW8gW1w8aHR0cHM6Ly93d3cucnN0dWRpby5jb20vcHJvZHVjdHMvcnN0dWRpby9kb3dubG9hZC9cPl0oaHR0cHM6Ly93d3cucnN0dWRpby5jb20vcHJvZHVjdHMvcnN0dWRpby9kb3dubG9hZC8pey51cml9DQoNCiMjIFIgc2V0dXAgXHwgUGFja2FnZXMNCg0KLSAgIEluc3RhbGwgcGFja2FnZQ0KDQpgYGB7cn0NCmluc3RhbGwucGFja2FnZXMoJ2RwbHlyJywgZGVwZW5jaWVzPVRSVUUpDQpgYGANCg0KLSAgIExvYWQgcGFja2FnZQ0KDQpgYGB7cn0NCmxpYnJhcnkoZHBseXIpDQpgYGANCg0KIyMgRG93bmxvYWQgZGF0YSBhbmQgb3BlbiBmaWxlIGluIFINCg0KMS4gIERvd25sb2FkIGRhdGEgZnJvbSBbZXhvcmJhc2VdKGh0dHA6Ly93d3cuZXhvcmJhc2Uub3JnL2V4b1JCYXNlVjIvZG93bmxvYWQvdG9JbmRleCkgd2Vic2l0ZS4NCg0KMi4gIE9wZW4gZmlsZSBpbiBSDQoNCmBgYHtyfQ0KaGNjX3JuYTwtcmVhZC5kZWxpbShmaWxlLmNob29zZSgpLGhlYWRlcj1UUlVFKQ0KaGVhbHRoeV9ybmE8LXJlYWQuZGVsaW0oZmlsZS5jaG9vc2UoKSxoZWFkZXI9VFJVRSkNCmBgYA0KDQojIyMjIE90aGVyIGZ1bmN0aW9ucyB0byBvcGVuIGZpbGUNCg0KIVtdKEltYWdlcy9BbHRjb2Rlc3JlYWRmaWxlLmpwZyl7d2lkdGg9IjQ1OSJ9DQoNCiMjIFIgcGFja2FnZXMgZm9yIERhdGEgd3JhbmdsaW5nDQoNCi0gICBBIHR5cGljYWwgZGF0YSBzY2llbmNlIHByb2plY3QgOg0KDQohW10oSW1hZ2VzL292ZXJ2aWV3JTIwb2YlMjBkYXRhc2NpLmpwZyl7d2lkdGg9IjUzNiJ9DQoNCipSZWZlcmVuY2U6IEdyb2xlbXVuZCwgRy4sICYgV2lja2hhbSwgSC4gKDIwMTcpLiBSIGZvciBEYXRhIFNjaWVuY2UuIE8nUmVpbGx5IE1lZGlhLioNCg0KLSAgIFRvIG1hbmlwdWxhdGUgdGhlIGRhdGEgZm9yIGRhdGEgdmlzdWFsaXphdGlvbi9pbnNpZ2h0cywgd2UgY2FuIHVzZSAiZHBseXIiIG9yICJ0aWR5dmVyc2UiIHBhY2thZ2UgaW4gUi4NCg0KICAgIDEuICBkcGx5cg0KDQogICAgICAgICFbXShJbWFnZXMvZHBseXIuanBnKXt3aWR0aD0iMzQwIn0NCg0KICAgICAgICAqUmVmZXJlbmNlOiA8aHR0cHM6Ly9kcGx5ci50aWR5dmVyc2Uub3JnLz4qDQoNCiAgICAyLiAgVGlkeXZlcnNlIC0gY29sbGVjdGlvbiBvZiBSIHBhY2thZ2VzIGZvciBkYXRhIHNjaWVuY2UNCg0KICAgICAgICAoZHBseXIgaXMgb25lIG9mIHRoZSBjb3JlIHBhY2thZ2VzIGluIHRpZHl2ZXJzZSkNCg0KICAgICAgICAhW10oSW1hZ2VzL3RpZHl2ZXJzZSUyMHBhY2thZ2UuanBnKXt3aWR0aD0iMzgwIn0NCg0KICAgICAgICAqUmVmZXJlbmNlOiA8aHR0cHM6Ly93d3cudGlkeXZlcnNlLm9yZy8+Kg0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyMgU3RlcCAxIERhdGEgd3JhbmdsaW5nIHVzaW5nIGRwbHlyIHBhY2thZ2VzDQoNCiMjIyMgMS4gTG9hZCBkcGx5ciBwYWNrYWdlDQoNCmBgYHtyfQ0KbGlicmFyeShkcGx5cikNCmBgYA0KDQojIyMjIDIuIEZpbHRlciByb3dzDQoNCmBgYHtyfQ0KIyBmaWx0ZXIgKCBkYXRhIGZyYW1lLCBjb2x1bW4gbmFtZSA9PSB2YWx1ZSkgDQojIGNhbiB1c2UgPCwgPD0sID4sID49DQpGR1JfZXhwcmVzc2lvbjwtZmlsdGVyKGhjY19ybmEsIEdlbmUuc3ltYm9sPT0iRkdSIikNCmhjYzAwNF9leHByZXNzaW9uPC1maWx0ZXIoaGNjX3JuYSwgSENDMDA0PD0xKQ0KDQojaWYgeW91IGhhdmUgbXVsdGlwbGUgY3JpdGVyaWENCiMgY2FuIHVzZSB8IChvciksICYgKGFuZCkNCmhjYzAwNF9oY2MwMDJfZXhwcmVzc2lvbjwtZmlsdGVyKGhjY19ybmEsIEhDQzAwNDw9MSAmIEhDQzAwMj4xKQ0KYGBgDQoNCiFbXShJbWFnZXMvZmlsdGVyJTIwY29kZXMuanBnKXt3aWR0aD0iNDE2In0NCg0KKlJlZmVyZW5jZToqIFsqaHR0cHM6Ly93d3cucnN0dWRpby5jb20vd3AtY29udGVudC91cGxvYWRzLzIwMTUvMDIvZGF0YS13cmFuZ2xpbmctY2hlYXRzaGVldC5wZGYqXShodHRwczovL3d3dy5yc3R1ZGlvLmNvbS93cC1jb250ZW50L3VwbG9hZHMvMjAxNS8wMi9kYXRhLXdyYW5nbGluZy1jaGVhdHNoZWV0LnBkZikNCg0KIyMjIyAzLiBBcnJhbmdlIHJvd3MNCg0KYGBge3J9DQojIGFycmFuZ2UgKGRhdGEgZnJhbWUsIGNvbHVtbiBuYW1lKQ0KaGNjX3NvcnQ8LWFycmFuZ2UoaGNjX3JuYSwgR2VuZS5zeW1ib2wpDQoNCiNzb3J0IGJ5IG1vcmUgdGhhbiBvbmUgdmFyaWFibGUNCmhjY19zb3J0PC1hcnJhbmdlKGhjY19ybmEsIEhDQzAwMSxHZW5lLnN5bWJvbCkNCmBgYA0KDQojIyMjIDQuIFNlbGVjdCBjb2x1bW5zDQoNCmBgYHtyfQ0KIyBzZWxlY3QgKGRhdGEgZnJhbWUsIGNvbHVtbiBuYW1lIDEsIGNvbHVtbiBuYW1lIDIpDQpoY2Nfc2VsZWN0PC1zZWxlY3QoaGNjX3JuYSwgR2VuZS5zeW1ib2wsIEhDQzAwNCkNCmBgYA0KDQojIyMjIDUuIFNlbGVjdCBhbGwgY29sdW1ucyBleGNlcHQgc3BlY2lmaWMgY29sdW1uDQoNCmBgYHtyfQ0KIyBzZWxlY3QgKGRhdGEgZnJhbWUsIC1jb2x1bW5zIHRoYXQgeW91IGRvbid0IHdhbnQpDQpoY2NfYWxsPC1zZWxlY3QoaGNjX3JuYSwgLWMoR2VuZS5zeW1ib2wsIEhDQzAwNCkpDQpgYGANCg0KIyMjIyA2LiBSZWNvZGUgZGF0YQ0KDQojIyMjIyMgZWcuIENhbGN1bGF0ZSBob3cgbWFueSBwYXRpZW50cyB0aGF0IGhhdmUgUk5BIGV4cHJlc3Npb24gXD4wIGFuZCBzdG9yZSB0aGlzIHZhbHVlIGluIGEgbmV3IGNvbHVtbiBjYWxsZWQgImNvdW50aGlnaGV4cCINCg0KYGBge3J9DQojIG11dGF0ZSAoZGF0YSBmcmFtZSwgbmV3IGNvbHVtbiBuYW1lID0gZnVuY3Rpb25zKQ0KaGNjX2hpZ2hleHA8LW11dGF0ZShoY2Nfcm5hLGNvdW50aGlnaGV4cD1yb3dTdW1zKGhjY19ybmE+MCkpDQpgYGANCg0KIyMjIyMjIGVnLiBSZWNvZGUgbnVtZXJpYyB2YWx1ZXMgdG8gY2F0ZWdvcmllcw0KDQpgYGB7cn0NCiMgbXV0YXRlIChkYXRhIGZyYW1lLCBuZXcgY29sdW1uIG5hbWUgPSBmdW5jdGlvbnMpDQpoY2NfaGlnaGV4cCA8LW11dGF0ZShoY2NfaGlnaGV4cCwgY2F0ID0gY2FzZV93aGVuKA0KICAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50aGlnaGV4cCA8IDUwIH4gImxvdyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgY291bnRoaWdoZXhwID49IDUwIH4gImhpZ2giKSkNCmBgYA0KDQojIyMjIDcuIFN1bW1hcml6ZSBkYXRhDQoNCmBgYHtyfQ0Kc3VtbWFyaXplKGhjY19oaWdoZXhwLG1lYW4oY291bnRoaWdoZXhwKSkNCmBgYA0KDQojIyMjIDguIEhhbmRsZSByZWxhdGlvbmFsIGRhdGEgKE11bHRpcGxlIHRhYmxlcyBvZiBkYXRhKQ0KDQohW10oSW1hZ2VzL3VuZGVyc3RhbmQlMjBqb2luLmpwZyl7d2lkdGg9IjE0OCJ9DQoNCiFbXShJbWFnZXMvSW5uZXJqb2luLmpwZyl7d2lkdGg9IjI0NSJ9DQoNCiFbXShJbWFnZXMvT3V0ZXJqb2luLmpwZyl7d2lkdGg9IjI5NSJ9DQoNCiFbXShJbWFnZXMvRmlsdGVyaW5nJTIwam9pbi5qcGcpe3dpZHRoPSIzNDgifQ0KDQoqUmVmZXJlbmNlOiBHcm9sZW11bmQsIEcuLCAmIFdpY2toYW0sIEguICgyMDE3KS4gUiBmb3IgRGF0YSBTY2llbmNlLiBPJ1JlaWxseSBNZWRpYS4qDQoNCmBgYHtyfQ0KIyBpbm5lcl9qb2luIChkYXRhIGZyYW1lIDEsIGRhdGEgZnJhbWUgMiwgYnk9ImtleSIpDQpoY2NfaGVhbHRoeTwtaW5uZXJfam9pbihoY2Nfcm5hLGhlYWx0aHlfcm5hLCBieT0iR2VuZS5zeW1ib2wiKQ0KYGBgDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIyMgRXhlcmNpc2UgMQ0KDQoxLiAgR2VuZXJhdGUgYSBtYXN0ZXJzaGVldCBieSBtZXJnaW5nICoqaGNjX3JuYSoqIGRhdGFzZXQgYW5kICoqaGVhbHRoeV9ybmEqKiBkYXRhc2V0LiBOYW1lIHRoZSBuZXcgbWFzdGVyc2hlZXQgYXMgKipoY2NfaGVhbHRoeSoqLg0KDQogICAgIyMjIyMjICpRdWVzdGlvbjogV2hhdCB0eXBlIG9mIGpvaW4gd2lsbCB5b3UgdXNlIGZvciB0aGlzIGRhdGFzZXQ/Kg0KDQoyLiAgU3VtbWFyaXplIG51bWJlciBvZiBnZW5lcyBmcm9tICoqaGNjX2hlYWx0aHkqKi4NCg0KMy4gIEluICoqaGNjX2hlYWx0aHkqKiwgdXNlIEdlbmUuc3ltYm9sIGNvbHVtbiBhcyByb3cgbmFtZXMgb2YgdGhlIHRhYmxlLg0KDQpgYGB7cn0NCiN3aXRob3V0IGFueSBwYWNrYWdlOiBkYXRhLmZyYW1lKGRhdGFzZXQgbmFtZSwgcm93Lm5hbWVzID0gY29sdW1uIG51bWJlcikNCiN1c2luZyB0aWR5dmVyc2UgcGFja2FnZTogY29sdW1uX3RvX3Jvd25hbWVzKGRhdGFzZXQgbmFtZSAsIHZhcj0ia2V5IikgDQpgYGANCg0KNC4gIFRoZW4sIHJlbW92ZSBnZW5lcyB0aGF0IGhhdmUgMCBleHByZXNzaW9uIGluIDkwJSBvZiBzYW1wbGVzIGluIHRoZSBkYXRhc2V0LiBOYW1lIHRoZSBkYXRhc2V0IGFzICoqaGNjX2hlYWx0aHlfaGlnaGV4cCoqDQo1LiAgU3VtbWFyaXplIHRoZSBudW1iZXIgb2YgZ2VuZXMgdGhhdCBoYXZlIGV4cHJlc3Npb24gdmFsdWUgXD4wIGluIDkwJSBvZiB0aGUgc2FtcGxlcy4NCjYuICBOb3JtYWxpemUgYWxsIGdlbmUgZXhwcmVzc2lvbnMgdXNpbmcgdGhlIGxvZzIgdHJhbnNmb3JtYXRpb24uIE5hbWUgdGhlIGRhdGFzZXQgYXMgKipoY2NfaGVhbHRoeV9sb2cqKg0KDQpgYGB7cn0NCiNsb2coKGRhdGEgZnJhbWUrMSksMikNCmBgYA0KDQojIyMjIEV4ZXJjaXNlIDEgYW5zd2Vycw0KDQpgYGB7cn0NCiNtZXJnZSBoY2Nfcm5hIHdpdGggaGVhbHRoeV9ybmENCmhjY19oZWFsdGh5PC1mdWxsX2pvaW4oaGNjX3JuYSxoZWFsdGh5X3JuYSkNCiMzNTUxNyBnZW5lcw0KDQojY29udmVydCBnZW5lIHN5bWJvbCBjb2x1bW4gdG8gcm93bmFtZXMNCmhjY19oZWFsdGh5IDwtIGRhdGEuZnJhbWUoaGNjX2hlYWx0aHksIHJvdy5uYW1lcyA9IDEpDQoNCiNyZW1vdmUgZ2VuZXMgdGhhdCBoYXMgMCBleHByZXNzaW9uIGluIDkwJSBvZiBzYW1wbGVzIGluIGJvdGggZGF0YXNldHMNCmhjY19oZWFsdGh5PC1tdXRhdGUoaGNjX2hlYWx0aHksY291bnQwPXJvd1N1bXMoaGNjX2hlYWx0aHk8PTApKQ0KaGNjX2hlYWx0aHlfaGlnaGV4cDwtZmlsdGVyKGhjY19oZWFsdGh5LGNvdW50MDw9MjA3KQ0KaGNjX2hlYWx0aHlfaGlnaGV4cDwtc2VsZWN0KGhjY19oZWFsdGh5X2hpZ2hleHAsLWNvdW50MCkNCiMxOCw1NzUgZ2VuZXMgbGVmdA0KDQojbG9nIHRyYW5zZm9ybWF0aW9uIG9mIHRoZSBkYXRhDQpoY2NfaGVhbHRoeV9sb2c8LWxvZygoaGNjX2hlYWx0aHlfaGlnaGV4cCsxKSwyKQ0KYGBgDQoNCiMjIEFib3V0IERhdGEgbm9ybWFsaXphdGlvbg0KDQotICAgTG9nIHRyYW5zZm9ybWF0aW9uIC0gdG8gbW9kZXJhdGUgdGhlIHZhcmlhbmNlIGFjcm9zcyB0aGUgbWVhbg0KDQohW10oSW1hZ2VzL0RhdGElMjBub3JtYWxpemF0aW9uLmpwZyl7d2lkdGg9IjYxNiJ9DQoNCi0gICBSZWFzb24gdG8gdXNlIExvZzIgaW5zdGVhZCBvZiBMb2cxMA0KDQohW10oSW1hZ2VzL2xvZzJyZWFzb24uanBnKXt3aWR0aD0iNjE0In0NCg0KLSAgIFJlYXNvbiBmb3IgZXhwcmVzc2lvbiB2YWx1ZSArIDEgYmVmb3JlIGxvZyB0cmFuc2Zvcm1hdGlvbg0KDQohW10oSW1hZ2VzL0RhdGElMjBub3JtYWxpemF0aW9uMi5qcGcpe3dpZHRoPSI2MTgifQ0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyMgU3RlcCAzYSBEYXRhIHZpc3VhbGl6YXRpb24gKEJhc2ljIGhpc3RvZ3JhbSkNCg0KIyMjIFIgcGFja2FnZXMgZm9yIGRhdGEgdmlzdWFsaXphdGlvbnMNCg0KYGBge3J9DQojSW5zdGFsbCBwYWNrYWdlcw0KaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIsZGVwZW5kZW5jaWVzPVRSVUUpDQppbnN0YWxsLnBhY2thZ2VzKCJnZ3B1YnIiLGRlcGVuZGVuY2llcz1UUlVFKQ0KDQojTG9hZCBwYWNrYWdlcw0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShnZ3B1YnIpDQpgYGANCg0KIVtdKEltYWdlcy9HR3Bsb3QyLmpwZykNCg0KKlJlZmVyZW5jZToqIFsqaHR0cHM6Ly9yc3R1ZGlvLmdpdGh1Yi5pby9jaGVhdHNoZWV0cy9kYXRhLXZpc3VhbGl6YXRpb24ucGRmKl0oaHR0cHM6Ly9yc3R1ZGlvLmdpdGh1Yi5pby9jaGVhdHNoZWV0cy9kYXRhLXZpc3VhbGl6YXRpb24ucGRmKQ0KDQpMZXQncyB2aXN1YWxpemUgdGhlIHRoZSBkYXRhc2V0IGJlZm9yZSBhbmQgYWZ0ZXIgbm9ybWFsaXphdGlvbg0KDQoxLiAgVHJhbnNwb3NlIHRoZSBkYXRhc2V0DQoNCmBgYHtyfQ0KI1RyYW5zcG9zZSB0aGUgZGF0YXNldHMgc28gdGhhdCB0aGUgUk5BIG5hbWVzIGFyZSBpbiBjb2x1bW5zIHdoaWxlIHNhbXBsZXMgYXJlIGluIHJvd3MNCnJhd190cmFuczwtZGF0YS5mcmFtZSh0KGhjY19oZWFsdGh5KSkNCm5vcm1hbGl6ZV90cmFuczwtZGF0YS5mcmFtZSh0KGhjY19oZWFsdGh5X2xvZykpDQpgYGANCg0KMi4gIERyYXcgaGlzdG9ncmFtIHVzaW5nIGdncGxvdA0KDQpgYGB7cn0NCiNzZWxlY3Qgb25lIG9mIHRoZSBSTkEgKEFCQ0IxIGFzIGV4YW1wbGUpDQojdXNlIGdncGxvdCB0byBkcmF3IGhpc3RvZ3JhbSBhbmQgbW9kaWZ5IHRoZSBiaW53aWR0aCBhbmQgY29sb3VyDQpyYXdncmFwaDwtZ2dwbG90KHJhd190cmFucyxhZXMoeD1BQkNCMSkpK2dlb21faGlzdG9ncmFtKGJpbndpZHRoPTAuNSxmaWxsPSJkZWVwc2t5Ymx1ZSIpDQpub3JtYWxpemVncmFwaDwtZ2dwbG90KG5vcm1hbGl6ZV90cmFucyxhZXMoeD1BQkNCMSkpK2dlb21faGlzdG9ncmFtKGJpbndpZHRoPTAuNSxmaWxsPSJkZWVwc2t5Ymx1ZSIpDQpgYGANCg0KMy4gIFBsYWNlIHRoZSBoaXN0b2dyYW0gc2lkZSBieSBzaWRlIGZvciBiZXR0ZXIgY29tcGFyaXNvbg0KDQpgYGB7cn0NCmdnYXJyYW5nZShyYXdncmFwaCxub3JtYWxpemVncmFwaCxuY29sPTIsbnJvdz0xLGxhYmVscz1jKCJyYXciLCJub3JtYWxpemUiKSkNCmBgYA0KDQojIyMgVXNlZnVsIHJlc291cmNlcyB0byBleHBsb3JlIGZ1cnRoZXINCg0KIVtdKEltYWdlcy9HR3Bsb3QyX290aGVycmVzb3VyY2VzLmpwZykNCg0KKioqU2F2ZSB0aGUgUiBjb2RlcyBhbmQgZW52aXJvbm1lbnQgLSBmb3IgbmV4dCBzZWN0aW9uISoqKg0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyMgQWRkaXRpb25hbCBpbmZvcm1hdGlvbiB0aGF0IG1heSBiZSB1c2VmdWwgaW4gZGF0YSB3cmFuZ2xpbmcNCg0KLSAgIEludHJvZHVjdGlvbiB0byBUaWR5dmVyc2UgcGFja2FnZQ0KDQpEYXRhIGZyYW1lIC1cPiB0aWJibGUgaW4gVGlkeXZlcnNlIHBhY2thZ2UNCg0KIVtdKEltYWdlcy9UaWJibGUuanBnKXt3aWR0aD0iNDE4In0NCg0KW2B0aWJibGUoKWBdKGh0dHBzOi8vdGliYmxlLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL3RpYmJsZS5odG1sKSBkb2VzIG11Y2ggbGVzcyB0aGFuIFtgZGF0YS5mcmFtZSgpYF0oaHR0cHM6Ly9yZHJyLmlvL3IvYmFzZS9kYXRhLmZyYW1lLmh0bWwpOiBpdCBuZXZlciBjaGFuZ2VzIHRoZSB0eXBlIG9mIHRoZSBpbnB1dHMgKGUuZy7CoGl0IG5ldmVyIGNvbnZlcnRzIHN0cmluZ3MgdG8gZmFjdG9ycyEpLCBpdCBuZXZlciBjaGFuZ2VzIHRoZSBuYW1lcyBvZiB2YXJpYWJsZXMsIGl0IG9ubHkgcmVjeWNsZXMgaW5wdXRzIG9mIGxlbmd0aCAxLCBhbmQgaXQgbmV2ZXIgY3JlYXRlcyBgcm93Lm5hbWVzKClgDQoNCipSZWZlcmVuY2U6IFtodHRwczovL3RpYmJsZS50aWR5dmVyc2Uub3JnLyM6XH46dGV4dD1UaWJibGVzJTIwYXJlJTIwZGF0YS4sYSUyMHZhcmlhYmxlJTIwZG9lcyUyMG5vdCUyMGV4aXN0KS4uKXsudXJpfV0oaHR0cHM6Ly90aWJibGUudGlkeXZlcnNlLm9yZy8jOn46dGV4dD1UaWJibGVzJTIwYXJlJTIwZGF0YS4sYSUyMHZhcmlhYmxlJTIwZG9lcyUyMG5vdCUyMGV4aXN0KS4uKXsudXJpfSkqDQoNCjEuICBMb2FkIHRpZHl2ZXJzZSBwYWNrYWdlDQoNCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpgYGANCg0KMi4gIENvbnZlcnQgZGF0YSBmcmFtZSB0byB0aWJibGUNCg0KYGBge3J9DQpoY2NfdGJsPC1hc190aWJibGUoaGNjX3JuYSkNCmhlYWx0aHlfdGJsPC1hc190aWJibGUoaGVhbHRoeV9ybmEpDQphbm5vdGF0aW9uX3RibDwtYXNfdGliYmxlKGFubm90YXRpb24pDQpgYGANCg0Kb3IgKipyZWFkX2NzdioqIGluc3RlYWQgb2YgKipyZWFkLmxpbSoqIG9yICoqcmVhZC5jc3YqKiB0byBpbXBvcnQgZGF0YSBhcyB0aWJibGUNCg0KMy4gIFRoZSBwb3dlciBvZiBwaXBlcyBpbiB0aWR5dmVyc2UNCg0KYGBge3J9DQojRm9yIGV4YW1wbGUsIGlmIHlvdSB3YW50IHRvIHNlbGVjdCBjb2x1bW4gdGhlbiBmaWx0ZXIsIG5vcm1hbGx5IHRoaXMgaXMgd2hhdCB5b3UgZG86DQpoY2Nfc2VsZWN0PC1zZWxlY3QoaGNjX3JuYSwgR2VuZS5zeW1ib2wsIEhDQzAwNCkNCmhjY19maWx0ZXI8LWZpbHRlcihoY2Nfc2VsZWN0LCBIQ0MwMDQ+PTEwMDApDQoNCiN3aXRoIHBpcGVzDQpoY2NfdG9jb21wYXJlPC1oY2Nfcm5hJT4lc2VsZWN0KEdlbmUuc3ltYm9sLCBIQ0MwMDQpJT4lZmlsdGVyKEhDQzAwND49MTAwMCkNCmBgYA0KDQotICAgVG8gc3BlY2lmeSBjb2x1bW4gbmFtZXMNCg0KYGBge3J9DQojY29sbmFtZXMoZGF0YXNldCBuYW1lKTwtZGF0YXNldFtmaXJzdCByb3csXQ0KYGBgDQoNCi0gICBUbyBjaGFuZ2UgZGF0YSB0eXBlIG9mIGEgY29sdW1uIChlZy4gY2hhcmFjdGVyIHRvIG51bWVyaWMpDQoNCmBgYHtyfQ0KI2RhdGFzZXQkY29sdW1uIG5hbWU8LWFzLm51bWVyaWMoZGF0YXNldCRjb2x1bW4gbmFtZSkNCmBgYA0KDQotICAgVG8gcmVtb3ZlIGR1cGxpY2F0ZXMNCg0KYGBge3J9DQojdXNpbmcgcGlwZXM6DQojZGF0YXNldCBuYW1lICU+JSBkaXN0aW5jdCAoc3BlY2lmaWMgY29sdW1uIG5hbWUsIC5rZWVwX2FsbD1UUlVFKQ0KDQojd2l0aG91dCB1c2luZyBwaXBlczoNCiNkaXN0aW5jdChkYXRhc2V0IG5hbWUsIHNwZWNpZmljIGNvbHVtbiwgLmtlZXBfYWxsPVRSVUUpDQpgYGANCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNClRoZSBFbmQgb2YgUGFydCAyDQo=